package awesome_pool

import (
	"bytes"
	"fmt"
	"io"
	"log"
	"net"
	"sync"
	"time"
)

/**
用队列自动维护线程池 , 取一个丢一个

*/
type connPool struct {
	Conn net.Conn
	fox  bool
}
type Pool struct {
	MaxRoutine int
	Length     int
	T          []*connPool
	FN         func() net.Conn
	Freex      chan int
	N          []*msg
	sync.RWMutex
}

func NewPool(maxRoutine int, dialAddress string) (*Pool, error) {
	p := new(Pool)
	p.T = make([]*connPool, maxRoutine)
	p.N = make([]*msg, maxRoutine)
	p.MaxRoutine = maxRoutine
	p.Freex = make(chan int, maxRoutine)
	p.FN = func() net.Conn {
		c, err := net.Dial("tcp", dialAddress)
		if err != nil {
			panic(err)
		}
		return c
	}
	for i := 0; i < maxRoutine; i++ {
		p.Length++
		p.N[i] = ready(p.FN(), i, dialAddress)
	}
	return p, nil
}

type msg struct {
	Conn  net.Conn
	write chan []byte
	read  chan []byte
	p     int
	addr  string
}

// get a idle net.Conn
// 应该用队列形式
func (p *Pool) Get() *msg {
	return p.N[0]
}
func ready(conn net.Conn, n int, addr string) *msg {
	m := &msg{
		Conn:  conn,
		write: make(chan []byte),
		read:  make(chan []byte),
		p:     n,
		addr:  addr,
	}
	go func(conn2 net.Conn, m2 *msg) {
		for {
			ms := <-m2.write
			var data []byte = make([]byte, 4096)
			_, err := m2.Conn.Write(ms)
			if err != nil {
				log.Panicln(74, err)
			}
			fmt.Println("write", string(ms))
			n, err := m2.Conn.Read(data)
			if err != nil {
				if err != io.EOF {
					log.Panicln(78, err)
				}
			}
			fmt.Println(string(data[:n]))
			m2.read <- data[:n]

		}
	}(conn, m)
	return m
}
func (m *msg) Start() {
	for {
		_, err := m.Conn.Write(<-m.write)
		if err != nil {
			log.Panicln(err)
		}
		var buf bytes.Buffer
		_, err = io.Copy(&buf, m.Conn)
		if err != nil {
			m.Conn.Close()
			m.Conn, _ = net.Dial("tcp", m.addr)
			log.Panicln(err)
		}
		m.read <- buf.Bytes()
	}
}
func (m *msg) Write(set []byte) {
	m.write <- set
}
func (m *msg) Read() []byte {
	r, ok := <-m.read
	if ok {
		return r
	}
	fmt.Println(ok, r)
	return nil
}
func (p *Pool) Free(n int) {
	p.Freex <- n
}
func main() {
	p, err := NewPool(5, "127.0.0.1:8800")
	if err != nil {
		return
	}
	c := p.Get()
	for {
		c.Write([]byte("hello"))
		fmt.Println(c.Read())
		<-time.After(time.Second)
	}

}
